package com.apes.hr.salary.rewardPunish.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.jpa.logger.ApesLoggerService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.EventUtil;
import com.apes.framework.util.MapUtil;
import com.apes.hr.base.model.Employee;
import com.apes.hr.base.model.TransferRecord;
import com.apes.hr.base.model.WorkPost;
import com.apes.hr.base.repository.EmployeeRepository;
import com.apes.hr.base.repository.HrDao;
import com.apes.hr.base.repository.TransferRecordRepository;
import com.apes.hr.base.repository.WorkPostRepository;
import com.apes.hr.salary.rewardPunish.model.RewardPunish;
import com.apes.hr.salary.rewardPunish.model.RewardPunishItem;
import com.apes.hr.salary.rewardPunish.model.RewardPunishType;
import com.apes.hr.salary.rewardPunish.repository.RewardPunishItemRepository;
import com.apes.hr.salary.rewardPunish.repository.RewardPunishRepository;
import com.apes.hr.salary.rewardPunish.repository.RewardPunishTypeRepository;
import com.apes.hr.transfer.model.QuitJobOrder;
import com.apes.hr.transfer.model.TransferApplicationItem;
import com.apes.hr.transfer.repository.QuitJobOrderRepository;
import com.apes.hr.transfer.repository.TransferApplicationItemRepository;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Branch;
import com.apes.scm.masterdata.frame.repository.BranchRepository;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.rbac.model.Post;
import com.apes.scm.rbac.model.User;
import com.apes.scm.rbac.repository.PostRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 功能：奖惩记录单服务
 *
 * @author HuJianlin
 * @create 2018-01-30 11:35
 */
@Service("rewardPunishService")
public class RewardPunishService extends DomainService {

    @Autowired
    RewardPunishRepository rewardPunishRepository;
    @Autowired
    RewardPunishItemRepository rewardPunishItemRepository;
    @Autowired
    RewardPunishTypeRepository rewardPunishTypeRepository;
    @Autowired
    EmployeeRepository employeeRepository;
    @Autowired
    PartyRoleRepository partyRoleRepository;
    @Autowired
    TransferApplicationItemRepository transferApplicationItemRepository;
    @Autowired
    TransferRecordRepository transferRecordRepository;
    @Autowired
    TeamRewardPunishItemService teamRewardPunishItemService;
    @Autowired
    DeptRepository deptRepository;
    @Autowired
    HrDao hrDao;
    @Autowired
    BranchRepository branchRepository;
    @Autowired
    WorkPostRepository workPostRepository;
    @Autowired
    EnumerationRepository enumerationRepository;
    @Autowired
    SequenceService sequenceService;
    @Autowired
    PostRepository postRepository;
    @Autowired
    QuitJobOrderRepository quitJobOrderRepository;

    /**
     * 功能：保存奖惩记录
     * @param request
     * @return
     */
    public RewardPunish save(SimpleRequest request) {
        RewardPunish rewardPunish = request.getO(RewardPunish.class);
        Post post = postRepository.findOne(request.getPostId());
        rewardPunish.setCancelUid(request.getPerson());
        rewardPunish.setCompany(post.getCompany());
        rewardPunish.setDept(post.getDept());
        rewardPunish.setState("create");
        return rewardPunishRepository.saveAndFlush(rewardPunish);
    }

    /**
     * 功能：检查数据
     * @param request
     */
    public RewardPunish checkData(SimpleRequest request){
        String id = request.get("id");
        int version = request.get("version");

        RewardPunish oldBill = rewardPunishRepository.findOne(id);
        if (oldBill == null) throw new RuntimeException("奖惩记录：" + request.get("id") + " 在系统中不存在。");
        if (oldBill.getVersion() != version ) throw new RuntimeException("记录已更新或已删除，请重新提交！");

        return oldBill;
    }

    /**
     * 功能：修改数据
     * @param request
     * @return
     */
    public RewardPunish update(SimpleRequest request){
        RewardPunish oldBill = checkData(request);
        RewardPunish rewardPunish = request.getO(RewardPunish.class);
        return rewardPunishRepository.saveAndFlush(rewardPunish);
    }

    /**
     * 功能：删除奖惩记录
     * @param request
     * @return
     */
    public String delete(SimpleRequest request) {
        RewardPunish oldBill = checkData(request);
        if (oldBill.getApproveDate() != null) throw new RuntimeException("奖惩记录：" + request.get("id") + " 在系统中已审批。");

        oldBill.setState("delete");
        rewardPunishRepository.saveAndFlush(oldBill);
        return "删除成功！";
    }

    /**
     * 功能：取消奖惩记录
     * @param request
     * @return
     */
    public RewardPunish cancel(SimpleRequest request) {
        RewardPunish oldBill = checkData(request);
        if (oldBill.getCancelDate() != null) throw new RuntimeException("奖惩记录：" + request.get("id") + " 在系统中已取消！");
        oldBill.setState("cancel");
        oldBill.setCancelDate(new Date());
        oldBill.setCancelUid(this.getPerson(request));

        return rewardPunishRepository.saveAndFlush(oldBill);
    }

    /**
     * 功能：审核奖惩记录
     *
     * @param request
     * @return
     */
    public RewardPunish approve(SimpleRequest request) {
        RewardPunish oldBill = checkData(request);
        if (oldBill.getApproveDate() != null) throw new RuntimeException("奖惩记录：" + request.get("id") + " 在系统中已审核。");

        oldBill.setState("approve");
        oldBill.setApproveDate(new Date());
        oldBill.setApproveUid(this.getPerson(request));
        return rewardPunishRepository.saveAndFlush(oldBill);
    }

    /**
     * 功能：发文奖惩记录
     *
     * @param request
     * @return
     */
    public RewardPunish sendOut(SimpleRequest request) {
        RewardPunish oldBill = checkData(request);
        RewardPunish rewardPunish = request.getO(RewardPunish.class);
        if (rewardPunish.getDocNumber()==null) throw new RuntimeException("奖惩文号不能为空");
        if (oldBill.getSendOutDate() != null) throw new RuntimeException("奖惩记录：" + request.get("id") + " 在系统中已发文。");
        rewardPunish.setState("sendOut");
        rewardPunish.setSendOutDate(new Date());
        rewardPunish.setSendOutUid(this.getPerson(request));
        //兑现日期为空，将兑现日期设置为发文时间
        if(rewardPunish.getCashDate() == null) rewardPunish.setCashDate(new Date());
        // 创建费用单
        createExpense(rewardPunish);

        return rewardPunishRepository.saveAndFlush(rewardPunish);
    }

    /**
     * 功能：退回奖惩记录
     * @param request
     * @return
     */
    public RewardPunish sendBack(SimpleRequest request){
        RewardPunish oldBill = checkData(request);
        RewardPunish rewardPunish = request.getO(RewardPunish.class);
        if (oldBill.getSendOutDate() != null) throw new RuntimeException("奖惩记录：" + request.get("id") + " 在系统中已发文。");
        rewardPunish.setState("create");
        rewardPunish.setApproveDate(null);
        rewardPunish.setApproveUid(null);
        return rewardPunishRepository.saveAndFlush(rewardPunish);
    }

    public RewardPunish findOne(SimpleRequest request) throws Exception {
        String id = request.get("id");
        return rewardPunishRepository.findOne(id);
    }
    public RewardPunish rewardItemInfo(SimpleRequest request)throws Exception{
        JSONObject jsonObject = request.getJO();
        String rewardPunishType_id =  request.get("rewardPunishType_id");
        RewardPunishType rewardPunishType = rewardPunishTypeRepository.findOne(rewardPunishType_id);
        if(rewardPunishType == null) throw new  RuntimeException("未找到对应的奖惩类型");
        JSONArray empArray = JSONObject.parseArray(jsonObject.getString("employee"));

        RewardPunish rewardPunish = new RewardPunish();
        Date createDate ;
        String code = sequenceService.getId("hr_Reward_Punish" );//获取序列;
        try {
            createDate = jsonObject.getDate("CreateDate");
            if (createDate==null) createDate =  new Date();
        } catch (Exception e){
            createDate =  new Date();
        }
        rewardPunish.setId(code);
        rewardPunish.setCreateDate(createDate);
        rewardPunish.setApproveDate(createDate);
        String sourceOrder = jsonObject.getString("SourceOrder");
        rewardPunish.setState("sendOut");   //单据状态设置为发文
        rewardPunish.setDocFileName(rewardPunishType.getFilename());//客服的节点考核写入到记录里
        rewardPunish.setRewardPunishType(rewardPunishType);
        rewardPunish.setQuotaType(rewardPunishType.getQuotaType());
        rewardPunish.setSourceName(jsonObject.getString("SourceName"));
        rewardPunish.setSourceOrder(sourceOrder);
        rewardPunish.setExplain(jsonObject.getString("note"));
        List<RewardPunishItem> rewardPunishItems = new ArrayList<>();
        for (int j=0;j< empArray.size();j++){
            JSONObject emp = empArray.getJSONObject(j);
            String empId = emp.getString("Id");
            Integer qty = emp.getInteger("qty");
            double amt = rewardPunishType.getAmt()* qty;
            Employee employee = employeeRepository.findOne("0"+empId);
            if(employee == null) throw new  RuntimeException("未找到对应的人员信息");
            RewardPunishItem rewardPunishItem = new RewardPunishItem();
            rewardPunishItem.setRewardPunish(rewardPunish);
            rewardPunishItem.setEmployee(employee);
            rewardPunishItem.setCompany(partyRoleRepository.findOne("1001"));
            rewardPunishItem.setWorkBranch(employee.getWorkBranch());
            rewardPunishItem.setWorkPost(employee.getPost());
            rewardPunishItem.setAffordLossAmt(0);
            rewardPunishItem.setCancelManageBonusMonth(0);
            rewardPunishItem.setCancelYearBonusMonth(0);
            rewardPunishItem.setDismiss(false);
            rewardPunishItem.setValue(rewardPunishType.getValue()*qty);
            rewardPunishItem.setAmt(amt);
            rewardPunishItem.setQty(qty);
            rewardPunishItems.add(rewardPunishItem);
        }
        rewardPunish.setRewardPunishItems(rewardPunishItems);
        rewardPunish.setCompany(partyRoleRepository.findOne("1001"));
        rewardPunish = rewardPunishRepository.saveAndFlush(rewardPunish);
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = formatter.format(createDate);
        Map map = new HashMap();
        map.put("rewardPunishId",rewardPunish.getId());
        map.put("CreateDate",dateString);
        invoke("hr.rewardPunish.updateCreateDate",map);
        return rewardPunish;
    }
    public void updateCreateDate(SimpleRequest request){
        String dateString = request.get("CreateDate");
        String id = request.get("rewardPunishId");
        //发文日期=制单日期
        rewardPunishRepository.updateCreateDate(id,dateString); //以ERP给的时间作为制单日期
    }

    public List synRewardPunishByOld(SimpleRequest request) throws Exception{
        List<RewardPunishType> rewardPunishTypeList = rewardPunishTypeRepository.findBySynInterface();
        List result = new ArrayList();
        for(RewardPunishType rewardPunishType: rewardPunishTypeList){
            try {
                String topic = "event:hr.hrTransferSyn.synRewardPunishByOld";
                JSONArray rows = (JSONArray) EventUtil.sendSynEvent(this, topic, rewardPunishType.getSynInterface()).stream().findFirst().get();
              if(rows != null){
                  rows.stream().forEach(row ->{
                      Map m = (Map) row;
                      m.put("rewardPunishType_id", rewardPunishType.getId());
                      result.add(m);
                  });
              }
            } catch (Exception e){
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 功能：下拉模糊查询使用
     * @param request
     * @return
     */
    public Page<RewardPunish> find(SimpleRequest request) {
        String key = "";
        try {
            key = request.get("key");
            return rewardPunishRepository.find(key,PageRequest.of(request.get("page"), request.get("size")) );
        } catch (Exception e) {
            return  rewardPunishRepository.findAll( PageRequest.of(request.get("page"), request.get("size")));
        }

    }
    /**
     * 功能：查询已发文记录
     * @param request
     * @return
     */
    public Page<RewardPunish> rewardPunishAppealFind(SimpleRequest request) {
        String key = "";
        try {
            key = request.get("key");
            return rewardPunishRepository.findByState(key,PageRequest.of(request.get("page"), request.get("size")) );
        } catch (Exception e) {
            List<Map> filters = request.get("condition");
            JSONObject djzt = new JSONObject();
            djzt.put("field","state");
            djzt.put("operator","EQ");
            djzt.put("value","sendOut");
            filters.add(djzt);
            return rewardPunishRepository.findAll(JpaDsl.toCriteria(filters),PageRequest.of(request.get("page"), request.get("size")) );
        }

    }



    //添加所有符合该岗位在职状态的员工
    public List<RewardPunishItem> findPenalty(SimpleRequest request){
        String rewardDate =  request.get("rewardDate");
        String rewardEndDate =  request.get("rewardEndDate");
        RewardPunishType rewardPunishType = request.getO("rewardPunishType",RewardPunishType.class);
        rewardPunishType = rewardPunishTypeRepository.findOne(rewardPunishType.getId());
        Set<WorkPost> workPosts = rewardPunishType.getpostSet();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date reward = new Date();
        Date end = new Date();
        Date oldYear = new Date();
        try {
            reward = sdf.parse(rewardDate);
            end = sdf.parse(rewardEndDate);
            Calendar c = Calendar.getInstance();
            c.setTime(reward);
            c.add(Calendar.YEAR, -1);
            oldYear = c.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        List<TransferRecord> recordList = new ArrayList<>();
        // 在岗状态为空 且 岗位为空 查全部
        if ( workPosts == null){
            recordList = transferRecordRepository.findByTransferOnAndTransferOut(reward,end);

            //在岗为空 且岗位不为空
        } else {
            List<String> workPostList = new ArrayList<>();
            workPosts.forEach(workPost -> {
                workPostList.add(workPost.getId());
            });
             recordList = transferRecordRepository.findByPostAndTransferOnAndTransferOut(reward,end,workPostList);
        }
        return setDistribution(recordList,rewardPunishType,reward,end);
    }

    //添加所有符合该岗位在职状态的员工
    public List<TransferRecord> findPenaltyTwo(SimpleRequest request){
        String rewardDate =  request.get("rewardDate");
        String rewardEndDate =  request.get("rewardEndDate");
        RewardPunishType rewardPunishType = request.getO("rewardPunishType",RewardPunishType.class);
        rewardPunishType = rewardPunishTypeRepository.findOne(rewardPunishType.getId());
        Set<WorkPost> workPosts = rewardPunishType.getpostSet();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date reward = new Date();
        Date end = new Date();
        try {
            reward = sdf.parse(rewardDate);
            end = sdf.parse(rewardEndDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        List<TransferRecord> recordList;
        // 在岗状态为空 且 岗位为空 查全部
        if ( workPosts == null){
            recordList = transferRecordRepository.findByTransferOnAndTransferOut(reward,end);
            //在岗为空 且岗位不为空
        } else {
            List<String> workPostList = new ArrayList<>();
            workPosts.forEach(workPost -> {
                workPostList.add(workPost.getId());
            });
            recordList = transferRecordRepository.findByPostAndTransferOnAndTransferOut(reward,end,workPostList);
        }
        return recordList;
    }


    //得到所有奖惩明细单
    public List<RewardPunishItem> getRewardPunishItems(SimpleRequest request){
        String rewardDate =  request.get("rewardDate");
        String rewardEndDate =  request.get("rewardEndDate");
        List<TransferRecord> recordList = request.getA("transferRecordList",TransferRecord.class);
        RewardPunishType rewardPunishType = request.getO("rewardPunishType",RewardPunishType.class);
        rewardPunishType = rewardPunishTypeRepository.findOne(rewardPunishType.getId());
        Date reward = new Date();
        Date end = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            reward = sdf.parse(rewardDate);
            end = sdf.parse(rewardEndDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return setDistribution(recordList,rewardPunishType,reward,end);
    }

    /**
     * 得最新的调动记录单
     * @param list
     * @return
     */
    public TransferRecord selectLastOne(List<TransferRecord> list) {
        TransferRecord card = list.get(0);

        Long dates[] = new Long[list.size()];
        for (int i = 1; i <= list.size(); i++) {
            // 把date类型的时间对象转换为long类型，时间越往后，long的值就越大，
            // 所以就依靠这个原理来判断距离现在最近的时间
            dates[i-1] = list.get(i-1).getTransferOn().getTime();
        }
        Long maxIndex = dates[0];// 定义最大值为该数组的第一个数
        for (int j = 0; j < dates.length; j++) {
            if (maxIndex < dates[j]) {
                maxIndex = dates[j];
                // 找到了这个j
                card = list.get(j);
            }
        }
        return card;
    }


    /**
     * 将信息写入分配明细
     * @param transferRecordList
     * @param rewardPunishType
     * @return
     */
    public List<RewardPunishItem> setDistribution (List<TransferRecord> transferRecordList,RewardPunishType rewardPunishType,Date reward,Date end) {
        List<RewardPunishItem> itemList = new ArrayList<>();
        RewardPunishType newRewardPunishType = rewardPunishTypeRepository.findOne(rewardPunishType.getId());
        double amtL = newRewardPunishType.getLimitAmtL();
        int valueL = newRewardPunishType.getLimitValueL();
        Calendar c = Calendar.getInstance();
        c.setTime(reward);
        c.add(Calendar.YEAR, -1);
        Date oldYear = c.getTime();
        transferRecordList.forEach(transferRecord -> {

            RewardPunishItem rewardPunishItem = new RewardPunishItem();
            Employee employee = transferRecord.getEmployee();
            Branch branch = transferRecord.getWorkBranch();
            Date openDay = branch.getOpenDay();
            Date transferOn = transferRecord.getTransferOn();
            rewardPunishItem.setQty(1);
            if (amtL!=0){
                rewardPunishItem.setAmt(amtL);
            } else {
                rewardPunishItem.setAmt(newRewardPunishType.getAmt());
            }
            if (valueL!=0){
                rewardPunishItem.setValue(valueL);
            } else {
                rewardPunishItem.setValue(newRewardPunishType.getValue());
            }
            rewardPunishItem.setOpenDay(openDay);
            rewardPunishItem.setDismiss(false);
            rewardPunishItem.setCompany(employee.getCompany());
            rewardPunishItem.setEmployee(employee);
            rewardPunishItem.setWorkBranch(branch);
            rewardPunishItem.setWorkPost(transferRecord.getPost());
            Enumeration onDutyState1 = transferRecord.getOnDutyState();
            rewardPunishItem.setOnDutyState(onDutyState1);
            rewardPunishItem.setCreateExpense("1001".equals(employee.getCompany().getId()));
            rewardPunishItem.setEntryDate(employee.getEntryDate());
            rewardPunishItem.setAffordLossAmt(0);
            rewardPunishItem.setManageBonusAmt(0);
            rewardPunishItem.setDemotion(false);
            rewardPunishItem.setRetain(false);
            rewardPunishItem.setTransferOn(transferOn);
            rewardPunishItem.setTransferOut(transferRecord.getTransferOut());
            Calendar cal = Calendar.getInstance();
            cal.setTime(transferOn);
            cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date transferLastDay = cal.getTime();
            transferOn = teamRewardPunishItemService.setTransferOnDate(transferOn);
            List<RewardPunishItem> rewardPunishList = rewardPunishItemRepository.findByRewardDate(oldYear,employee);
            double valueTotal =0;
            for (RewardPunishItem Item: rewardPunishList) {
                double value = Item.getValue();
                valueTotal += value;
            }
            //需改
//            int valueTotal = this.getRewardPunishValue(employee,reward);// 12个月的处罚分合计
            rewardPunishItem.setEmpValueTotal(valueTotal);
            if(rewardPunishType.getCategory().getDescription().equals("处罚")) {
                String transferApplicationItemId = transferRecord.getTransferApplicationItemId();
                //查询 两个 时间段 是否有交集
                LocalDate rewardLocal = DateToLocaleDate(reward).with(TemporalAdjusters.firstDayOfMonth());
                LocalDate endLocal = DateToLocaleDate(end).with(TemporalAdjusters.lastDayOfMonth());
                List<TransferApplicationItem>  items = transferApplicationItemRepository.findToRewardPunish(employee.getId(),ULocalDateToDate(rewardLocal),ULocalDateToDate(endLocal));
                // 当 支援单 > 7天时，且支援时间在 奖惩期间内
                if (!items.isEmpty()){
                    rewardPunishItem.setNoPenalty(true);
                    rewardPunishItem.setAmt(0);
                    rewardPunishItem.setValue(0);
                    rewardPunishItem.setAffordLossAmt(0);
                    rewardPunishItem.setCancelManageBonusMonth(0);
                    rewardPunishItem.setCancelYearBonusMonth(0);
                    rewardPunishItem.setManageBonusAmt(0);
                }
                //新开社区店3个月免考核，不满完整自然月的也计为1个月;
                if (openDay !=null && !reward.after(lastDay(dateAdd(openDay,2)))){
                    rewardPunishItem.setNoPenalty(true);
                } else {
                    if (transferApplicationItemId == null || transferApplicationItemId.isEmpty()) {
                        //新入职两个月内免罚
                        if (reward.before(dateAdd(transferOn, 2))) {
                            rewardPunishItem.setNoPenalty(true);
                        }
                    } else {
                        //需改
                        TransferApplicationItem transferApplicationItem = transferApplicationItemRepository.findOne(Integer.valueOf(transferApplicationItemId));
                        String description = transferApplicationItem.getHrTransferKind().getDescription();
                        String onDutyState = new String();
                        if (onDutyState1 != null) {
                            onDutyState = onDutyState1.getDescription();
                        }

                        // 调动性质为晋职，当月免罚 ；为平调的，两个月免罚 ；为代理期的，两个月免罚 ;

                        if (description.equals("晋职") && !reward.after(transferLastDay)) {
                            rewardPunishItem.setNoPenalty(true);
                        } else if (description.equals("平调") && reward.before(dateAdd(transferOn, 2))) {
                            rewardPunishItem.setNoPenalty(true);
                        } else if (onDutyState.equals("代理期") && reward.before(dateAdd(transferOn, 2))) {
                            rewardPunishItem.setNoPenalty(true);
                        }

                    }
                }
            }else {
                rewardPunishItem.setNoPenalty(false);
            }
            itemList.add(rewardPunishItem);
        });
        return itemList;
    }

    /**
     * 将离职信息写入分配明细
     * @param rewardPunishType
     * @param reward
     * @param end
     * @return
     */
    public List<RewardPunishItem> setDimissionDistribution (Employee employee,RewardPunishType rewardPunishType,Date reward,Date end) {
        List<RewardPunishItem> itemList = new ArrayList<>();
        RewardPunishType newRewardPunishType = rewardPunishTypeRepository.findOne(rewardPunishType.getId());
        double amtL = newRewardPunishType.getLimitAmtL();
        int valueL = newRewardPunishType.getLimitValueL();
        Calendar c = Calendar.getInstance();
        c.setTime(reward);
        c.add(Calendar.YEAR, -1);
        Date oldYear = c.getTime();


            RewardPunishItem rewardPunishItem = new RewardPunishItem();
            Branch branch = employee.getWorkBranch();
            Date openDay = branch.getOpenDay();
        List<QuitJobOrder> byEmployee = quitJobOrderRepository.findByEmployee(employee);
        QuitJobOrder quitJobOrder = byEmployee.get(byEmployee.size() - 1);
            Date transferOn = quitJobOrder.getRealLastDay();//离职日期
            rewardPunishItem.setQty(1);
            if (amtL!=0){
                rewardPunishItem.setAmt(amtL);
            } else {
                rewardPunishItem.setAmt(newRewardPunishType.getAmt());
            }
            if (valueL!=0){
                rewardPunishItem.setValue(valueL);
            } else {
                rewardPunishItem.setValue(newRewardPunishType.getValue());
            }
            rewardPunishItem.setOpenDay(openDay);//门店开业时间
            rewardPunishItem.setDismiss(false);//开除
            rewardPunishItem.setCompany(employee.getCompany());//所属公司
            rewardPunishItem.setEmployee(employee);//员工
            rewardPunishItem.setWorkBranch(branch);//工作部门
            rewardPunishItem.setWorkPost(employee.getPost());//工作岗位

//            Enumeration onDutyState1 = employee.getOnDutyState();
//            rewardPunishItem.setOnDutyState(onDutyState1);//在职状态(onDutyState)
            rewardPunishItem.setCreateExpense("1001".equals(employee.getCompany().getId()));//是否生成费用单
            rewardPunishItem.setEntryDate(employee.getEntryDate());//入职日期
            rewardPunishItem.setAffordLossAmt(0);//承担损失金额
            rewardPunishItem.setManageBonusAmt(0);//服务管理奖金少得
            rewardPunishItem.setDemotion(false);//是否降职
            rewardPunishItem.setRetain(false);//是否留用察看
            rewardPunishItem.setTransferOn(employee.getEntryDate());//调至日期
            rewardPunishItem.setTransferOut(transferOn);//调离日期

            List<RewardPunishItem> rewardPunishList = rewardPunishItemRepository.findByRewardDate(oldYear,employee);
            int valueTotal =0;
            for (RewardPunishItem Item: rewardPunishList) {
                double value = Item.getValue();
                valueTotal += value;
            }
            //需改
//            int valueTotal = this.getRewardPunishValue(employee,reward);// 12个月的处罚分合计
            rewardPunishItem.setEmpValueTotal(valueTotal);


            {
                rewardPunishItem.setNoPenalty(false);
            }
            itemList.add(rewardPunishItem);

        return itemList;
    }


    /**
     *   员工已发文的连续12个月行政奖罚分合计
     * @param employee
     * @param reward
     * @return
     */
    public double getRewardPunishValue(Employee employee,Date reward){
        // 给定日期的前一年的日期

        Calendar c = Calendar.getInstance();
        c.setTime(reward);
        c.add(Calendar.YEAR, -1);
        Date oldYear = c.getTime();

        double valueTotal = 0 ;
        List<RewardPunishItem> rewardPunishList = rewardPunishItemRepository.findByRewardDate(oldYear,employee);
//        rewardPunishList.forEach(o -> {
//            RewardPunishItem rewardPunishItem  = JSON.parseObject(JSON.toJSONString(rewardPunishList.get("key")),RewardPunishItem.class)
//        });
        for (RewardPunishItem rewardPunishItem: rewardPunishList) {
            double value = rewardPunishItem.getValue();
            valueTotal += value;
        }
        return valueTotal;
    }
    /**
     * 传入的时间加一天
     * @param date
     * @return
     */
    private Date dateAdd(Date date,int i){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, i);//+1今天的时间加1月
        return calendar.getTime();
    }

    /**
     * 得到月尾
     * @param date
     * @return
     */
    private Date lastDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }

    public  List<RewardPunishItem> findTransferRecordByEmployee(SimpleRequest request){
        String rewardDate =  request.get("rewardDate");
        String rewardEndDate =  request.get("rewardEndDate");
        RewardPunishType rewardPunishType = request.getO("rewardPunishType",RewardPunishType.class);
        rewardPunishType = rewardPunishTypeRepository.findOne(rewardPunishType.getId());
        Employee employee = employeeRepository.findOne(request.getO("Employee",Employee.class).getId());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date reward = new Date();
        Date end = new Date();
        try {
            reward = sdf.parse(rewardDate);
            end = sdf.parse(rewardEndDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Set<WorkPost> workPosts = rewardPunishType.getpostSet();
        List<String> workPostList = new ArrayList<>();
        List<TransferRecord> recordList = new ArrayList<>();
        if (workPosts!=null) {
            workPosts.forEach(workPost -> {
                workPostList.add(workPost.getId());
            });
            recordList = transferRecordRepository.findByEmployeeAndPostList(employee,workPostList);
        } else {
            recordList = transferRecordRepository.findByEmployee(employee);
        }

        Map<Employee,List<TransferRecord>> empTransferList = new HashMap<>();
        List<TransferRecord> transferRecordList;
        empTransferList.put(employee,recordList);
        transferRecordList = teamRewardPunishItemService.screenTransfer(empTransferList,reward,end);

        if (transferRecordList==null || transferRecordList.isEmpty()) return setDimissionDistribution(employee,rewardPunishType,reward,end);
        TransferRecord transferRecord = selectLastOne(transferRecordList);
        transferRecordList = new ArrayList<>();
        transferRecordList.add(transferRecord);
        return setDistribution(transferRecordList,rewardPunishType,reward,end);
    }

    /**
     * date转localDate
     * @param date
     * @return
     */
    public static LocalDate DateToLocaleDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId  = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDate();
    }

    /**
     * 根据奖惩单号 和 当前登录人 找到奖惩明细
     * @param request
     */
    public RewardPunishItem findByIdAndEmployee(SimpleRequest request) {
        String id = request.get("id");
        Employee employee = employeeRepository.findByParty(((PartyRole)request.getPerson()).getParty());
        return rewardPunishItemRepository.findByIDAndEmployee(id,employee);
    }


    public Page findAll(SimpleRequest request){
        List<Map> filters = request.get("condition");
        filters.stream().forEach(map->{
            if (map.get("field").equals("creatorByAdmin")){
                 if((int)map.get("value")==0){
                     map.put("field","rewardPunishType.synInterface");
                     map.put("value",null);
                     map.put("operator","EQ");
                 }else {
                     map.put("field","rewardPunishType.synInterface");
                     map.put("value",null);
                     map.put("operator","NE");
                 }
           }
        });
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        return rewardPunishRepository.findAll(JpaDsl.toCriteria(filters), PageRequest.of(request.get("page"), request.get("size"), sort));
    }


    /**
     * 导入 后 的数据 判断 人员是否免罚
     * @param request
     * @return
     */
    public RewardPunish getNoPenalty(SimpleRequest request){
        RewardPunish rewardPunish = request.getO(RewardPunish.class);
        RewardPunishType rewardPunishType = rewardPunish.getRewardPunishType();
        Date reward = rewardPunish.getRewardDate();
        Date end = rewardPunish.getRewardEndDate();

        rewardPunish.getRewardPunishItems().stream().forEach(rewardPunishItem -> {
            Employee employee = rewardPunishItem.getEmployee();
            Map<Employee,List<TransferRecord>> empTransferList = transferRecordRepository.findByEmployee(employee).stream().collect(Collectors.groupingBy(TransferRecord::getEmployee));
            List<TransferRecord> transferRecordList = teamRewardPunishItemService.screenTransfer(empTransferList,reward,end);
            transferRecordList.forEach(transferRecord -> {
                Date openDay = transferRecord.getWorkBranch().getOpenDay();
                Date transferOn = transferRecord.getTransferOn();
                Enumeration onDutyState1 = transferRecord.getOnDutyState();
                Calendar cal = Calendar.getInstance();
                cal.setTime(transferOn);
                cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Date transferLastDay = cal.getTime();
                if(rewardPunishType.getCategory().getDescription().equals("处罚")) {
                    String transferApplicationItemId = transferRecord.getTransferApplicationItemId();
                    //查询 两个 时间段 是否有交集
                    LocalDate rewardLocal = DateToLocaleDate(reward).with(TemporalAdjusters.firstDayOfMonth());
                    LocalDate endLocal = DateToLocaleDate(end).with(TemporalAdjusters.lastDayOfMonth());
                    List<TransferApplicationItem>  items = transferApplicationItemRepository.findToRewardPunish(employee.getId(),ULocalDateToDate(rewardLocal),ULocalDateToDate(endLocal));
                    // 当 支援单 > 7天时，且支援时间在 奖惩期间内
                    if (!items.isEmpty()){
                        rewardPunishItem.setNoPenalty(true);
                        rewardPunishItem.setAmt(0);
                        rewardPunishItem.setValue(0);
                        rewardPunishItem.setAffordLossAmt(0);
                        rewardPunishItem.setCancelManageBonusMonth(0);
                        rewardPunishItem.setCancelYearBonusMonth(0);
                        rewardPunishItem.setManageBonusAmt(0);
                    }
                    //新开社区店3个月免考核，不满完整自然月的也计为1个月;
                    if (openDay !=null && !reward.after(lastDay(dateAdd(openDay,2)))){
                        rewardPunishItem.setNoPenalty(true);
                    } else {
                        if (transferApplicationItemId == null || transferApplicationItemId.isEmpty()) {
                            //新入职两个月内免罚
                            if (reward.before(dateAdd(transferOn, 2))) {
                                rewardPunishItem.setNoPenalty(true);
                            }
                        } else {
                            //需改
                            TransferApplicationItem transferApplicationItem = transferApplicationItemRepository.findOne(Integer.valueOf(transferApplicationItemId));
                            String description = transferApplicationItem.getHrTransferKind().getDescription();
                            String onDutyState = new String();
                            if (onDutyState1 != null) {
                                onDutyState = onDutyState1.getDescription();
                            }

                            // 调动性质为晋职，当月免罚 ；为平调的，两个月免罚 ；为代理期的，两个月免罚 ;

                            if (description.equals("晋职") && !reward.after(transferLastDay)) {
                                rewardPunishItem.setNoPenalty(true);
                            } else if (description.equals("平调") && reward.before(dateAdd(transferOn, 2))) {
                                rewardPunishItem.setNoPenalty(true);
                            } else if (onDutyState.equals("代理期") && reward.before(dateAdd(transferOn, 2))) {
                                rewardPunishItem.setNoPenalty(true);
                            }

                        }
                    }
                }else {
                    rewardPunishItem.setNoPenalty(false);
                }
            });
        });
        return rewardPunishRepository.saveAndFlush(rewardPunish);
    }

    /**
     *    java.time.LocalDate --> java.util.Date
     */
    public Date ULocalDateToDate(LocalDate localDate) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        Date date = Date.from(instant);
        return date;
    }


    private boolean setPenalty(TransferRecord transferRecord,RewardPunishType rewardPunishType,Date reward ,Date end,Employee employee){
        Date openDay = transferRecord.getWorkBranch().getOpenDay();
        Date transferOn = transferRecord.getTransferOn();
        Enumeration onDutyState1 = transferRecord.getOnDutyState();
        Calendar cal = Calendar.getInstance();
        cal.setTime(transferOn);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date transferLastDay = cal.getTime();
        if(rewardPunishType.getCategory().getDescription().equals("处罚")) {
            String transferApplicationItemId = transferRecord.getTransferApplicationItemId();
            //查询 两个 时间段 是否有交集
            LocalDate rewardLocal = DateToLocaleDate(reward).with(TemporalAdjusters.firstDayOfMonth());
            LocalDate endLocal = DateToLocaleDate(end).with(TemporalAdjusters.lastDayOfMonth());
            List<TransferApplicationItem>  items = transferApplicationItemRepository.findToRewardPunish(employee.getId(),ULocalDateToDate(rewardLocal),ULocalDateToDate(endLocal));
            // 当 支援单 > 7天时，且支援时间在 奖惩期间内
            if (!items.isEmpty()){
               return true;
            }
            //新开社区店3个月免考核，不满完整自然月的也计为1个月;
            if (openDay !=null && !reward.after(lastDay(dateAdd(openDay,2)))){
                return true;
            } else {
                if (transferApplicationItemId == null || transferApplicationItemId.isEmpty()) {
                    //新入职两个月内免罚
                    if (reward.before(dateAdd(transferOn, 2))) {
                        return true;
                    }
                } else {
                    //需改
                    TransferApplicationItem transferApplicationItem = transferApplicationItemRepository.findOne(Integer.valueOf(transferApplicationItemId));
                    String description = transferApplicationItem.getHrTransferKind().getDescription();
                    String onDutyState = new String();
                    if (onDutyState1 != null) {
                        onDutyState = onDutyState1.getDescription();
                    }

                    // 调动性质为晋职，当月免罚 ；为平调的，两个月免罚 ；为代理期的，两个月免罚 ;

                    if (description.equals("晋职") && !reward.after(transferLastDay)) {
                        return true;
                    } else if (description.equals("平调") && reward.before(dateAdd(transferOn, 2))) {
                        return true;
                    } else if (onDutyState.equals("代理期") && reward.before(dateAdd(transferOn, 2))) {
                        return true;
                    }

                }
            }
        }else {
            return false;
        }
        return false;
    }

    /**
     * 通用导入
     *
     * @param request
     * @return
     */
    public JSONObject beImportReward(SimpleRequest request) {
        JSONObject importData = request.get("importData");//Excel信息
        //定义变量
        JSONArray field = (JSONArray) request.get("data");
        List<Map> datas = request.get("data");
        JSONArray fieldValue =(JSONArray) request.get("fieldValue");
        JSONObject value = fieldValue.getJSONObject(0);
        Date rewardDate = new Date();
        Date rewardEndDate = new Date();
        try {
            rewardDate = value.getDate("rewardDate");
        } catch (Exception e){
            String rew =  value.getString("rewardDate");
            rewardDate = StringToDate(rew,DateUtil.SHOW_DATETIME_UTC_FORMAT);
            String rewardEnd =  value.getString("rewardEndDate");
            rewardEndDate = StringToDate(rewardEnd,DateUtil.SHOW_DATETIME_UTC_FORMAT);
        }
        Optional<RewardPunishType> rewardPunishType = rewardPunishTypeRepository.findById(value.getJSONObject("rewardPunishType").getString("id"));
        //List<ImportCarExecute> importCarExecutes = new ArrayList<>(); //用于批量保存车型配置中间表

        JSONObject exclObject = new JSONObject();                  //返回值

        JSONArray exclArr = new JSONArray();            //行内容
        JSONArray headerName = new JSONArray();         //头部
        JSONArray fieldName = new JSONArray();          //field
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
//        AtomicReference<Employee> employee = new AtomicReference<>(new Employee());
        for (int i = 0; i < field.size(); i++) {
            JSONObject webTab = (JSONObject) field.get(i);
            headerName.add(webTab.get("name"));
            fieldName.add(webTab.get("field"));
        }

        //业务逻辑
        Date finalRewardDate = rewardDate;
        Date finalRewardEndDate = rewardEndDate;
        importData.forEach((k, v) -> {

            //获得value ===Excel内容
            JSONArray excl = (JSONArray) v;
            JSONArray header = (JSONArray) excl.get(0); //首行数据

            for (int i = 0; i < excl.size(); i++) {  //遍历每一行

                if (i == 0) { //跳过首行
                    exclArr.add(headerName);
                    continue;
                }

                JSONArray lineLong = (JSONArray) excl.get(i); //当前行
                //合并2个list为一个map,KEY为首行数据，Value为当前行数据
                Map<String, Object> rst = IntStream.range(0, header.size()).collect(LinkedHashMap<String, Object>::new,
                        (m, key) -> m.put(header.getString(key).replace(";", ""),
                                key >= lineLong.size() ? "" : (lineLong.getString(key) == null ? "" : lineLong.getString(key).trim().replaceAll("[\\s]{2,}", " "))),
                        (m1, m2) -> {
                        });
                String name = String.valueOf(rst.get("员工"));
                Employee employee = new Employee();
                try {
                    employee = employeeRepository.findByIdOrName(name,name);
                    if (employee == null ) {
                        throw new RuntimeException(name + " 在表中不存在，导入终止。");
                    }
                } catch (Exception e) {
                    throw new RuntimeException(name + " 在表中不存在，导入终止。");
                }
                if (transferRecordRepository.findByTransferOnAndTransferOutAndEmployee(finalRewardDate, finalRewardEndDate, employee.getId()).isEmpty()){
                    throw new RuntimeException(name + " 不符合条件，不能导入！");
                }
                Set<WorkPost> workPosts = rewardPunishType.get().getpostSet();
                List<String> workPostList = new ArrayList<>();
                List<TransferRecord> recordList = new ArrayList<>();
                if (workPosts!=null) {
                    workPosts.forEach(workPost -> {
                        workPostList.add(workPost.getId());
                    });
                    recordList = transferRecordRepository.findByEmployeeAndPostList(employee,workPostList);
                } else {
                    recordList = transferRecordRepository.findByEmployee(employee);
                }
                Map<Employee,List<TransferRecord>> empTransferList = new HashMap<>();
                List<TransferRecord> transferRecordList;
                empTransferList.put(employee,recordList);
                transferRecordList = teamRewardPunishItemService.screenTransfer(empTransferList,finalRewardDate,finalRewardEndDate);
                if (transferRecordList==null || transferRecordList.isEmpty()) throw new RuntimeException(name + "员工不合条件!");
                TransferRecord transferRecord = selectLastOne(transferRecordList);

//                TransferRecord transferRecord = transferRecordRepository.findByTransferOnAndTransferOutAndEmployee(finalRewardDate, finalRewardEndDate, employee.getId()).get(0);
                boolean penalty = setPenalty(transferRecord,rewardPunishType.get(), finalRewardDate, finalRewardEndDate, employee);
                rst.put("员工",employee);
                rst.put("所属公司", employee.getCompany());
                rst.put("是否免罚",penalty);
                rst.put("工作部门",transferRecord.getWorkBranch());
                rst.put("工作岗位",transferRecord.getPost());
                if(employee.getEntryDate() == null){
                    rst.put("入职日期","");
                } else {
                    rst.put("入职日期",format.format(employee.getEntryDate()));
                }
                rst.put("调至日期",format.format(transferRecord.getTransferOn()));
                if(transferRecord.getOnDutyState() == null){
                    rst.put("在岗状态","");
                } else {
                    rst.put("在岗状态",transferRecord.getOnDutyState());
                }
                if(transferRecord.getTransferOut() == null){
                    rst.put("调离日期","");
                } else {
                    rst.put("调离日期",format.format(transferRecord.getTransferOut()));
                }
                if(transferRecord.getWorkBranch().getOpenDay() == null){
                    rst.put("门店开业时间","");
                } else {
                    rst.put("门店开业时间",format.format(transferRecord.getWorkBranch().getOpenDay()));
                }
                rst.put("是否解除劳动合同",Objects.equals(String.valueOf(rst.get("是否解除劳动合同")),"是") ? true : false);
                rst.put("是否降职",Objects.equals(String.valueOf(rst.get("是否降职")),"是") ? true : false);
                rst.put("是否留用察看",Objects.equals(String.valueOf(rst.get("是否留用察看")),"是") ? true : false);
                rst.put("是否暂缓执行",Objects.equals(String.valueOf(rst.get("是否暂缓执行")),"是") ? true : false);
                rst.put("生成费用单",Objects.equals(String.valueOf(rst.get("生成费用单")),"是") ? true : false);

                List valueList =  rst.entrySet().stream().map(Map.Entry::getValue).collect(Collectors.toList());
                exclArr.add(valueList);
            }
            exclObject.put(k, exclArr);
        });


        return exclObject;
    }

    // 创建费用单
    public void createExpense(RewardPunish rewardPunish) {
        // 是否免罚为否，生成费用单为是，在岗状态为股东，奖惩单状态为发文,
        List<RewardPunishItem> rewardPunishItems = rewardPunish.getRewardPunishItems();
        Map<String, List<RewardPunishItem>> collect = rewardPunishItems.stream().filter(rewardPunishItem -> {
            return !rewardPunishItem.isNoPenalty() &&
                    !rewardPunishItem.getCompany().getId().equals("1001") &&
                    rewardPunishItem.isCreateExpense() &&
                    "sendOut".equals(rewardPunish.getState());
        }).collect(Collectors.groupingBy(v -> v.getCompany().getId()));
        if (collect.isEmpty()) return;
        // 生成费用单
        List<Map> item = new ArrayList<>();
        collect.forEach((k,v) ->{
            item.add(MapUtil.mapper(
                    "company",  MapUtil.mapped(partyRoleRepository.findOne(k)),
                    "settlePolicy", "奖惩单号:" +rewardPunish.getId() + " 文件名:" + rewardPunish.getDocFileName(),
                    "expenseType", MapUtil.mapped(invoke("fn.expenseType.findOne", MapUtil.mapper("id", "B10"))),
                    "amount", v.stream().mapToDouble(RewardPunishItem::getAmt).sum() * - 1,
                    "periodStart", rewardPunish.getRewardDate(),
                    "periodEnd", rewardPunish.getRewardEndDate(),
                    "remark", "奖惩单号:" +rewardPunish.getId() + " 奖罚文号:" +rewardPunish.getDocNumber() +" 文件名:" + rewardPunish.getDocFileName() +
                              " 创建人:" + rewardPunish.get_creator().getName()
            ));


        });

        //费用单创建人取奖惩记录单发文人
        Model result = invoke("fn.expense.createRewardPunish", MapUtil.mapper("company", MapUtil.mapped(partyRoleRepository.findOne("1007")),
                "expenseItems", item,"creator", rewardPunish.get_creator().getId()));

        //费用单直接审核
        invoke("fn.rewardPunishExpense.approve", MapUtil.mapped(result));

    }

    private void logger(Model model, String description, String workPostName){
        SpringManager.getBean(ApesLoggerService.class).sendSynEvent("event:ir.logger.create", MapUtil.mapper(
                "businessType", model.getInnerBusinessType(),
                "businessKey", model.getInnerBusinessKey(),
                "operate", description,
                "workPostName", workPostName,
                "audit", model.getAudit(),
                "operator_id", model.getUserId()));
    }

    public String jointName(List<RewardPunishItem> items){
        StringBuffer resultBuffer = new StringBuffer();
        for (int i = 0; i < items.size(); i++) {
            String name = items.get(i).getEmployee().getName();
            if (i == 0) {
                resultBuffer.append(name);
            } else {
                resultBuffer.append("、" + name);
            }
        }
        return resultBuffer.toString();
    }
    /**
     * String --> Date
     * @param endDate
     * @param dateFormat
     * @return
     */
    public Date StringToDate( String endDate, String dateFormat){
        DateFormat format = new SimpleDateFormat(dateFormat);
        Date eDate = null;
        try {
            eDate = format.parse(endDate);
        }catch  (ParseException e) {
            e.printStackTrace();
        }
        return eDate;
    }
}
